#include "mgos.h"
#include "mongoose.h"
#include "mgos_pwm.h"
#include "mgos_blynk.h"
#include "stdint.h"
#include "string.h"
#include "pid_v1.h"
#include "ds18b20.h"
#include "Cook.h"

#define COUNT 100
#define DATA_DS18B20 5 //D1
#define DRIVER 16	  // D0
#define FAN 4		   // D2
#define FREQ 100

// Blynk定义
#define v_btn_fan 2
#define v_btn_egg 3
#define v_slider 5
#define v_temp 4
#define v_freq_levle 8
#define v_led 7

// 计数：1秒
static int counter = 0;
// Define 设置点温度，ds18b20输入，PWM输出
static double Setpoint, Input, Output;
// Define the aggressive and conservative Tuning Parameters
// static double aggKp = 4, aggKi = 0.2, aggKd = 1;
static double consKp = 1, consKi = 0.05, consKd = 0.25;
static PID *myPID;
// static struct mg_connection *s_blynk_conn = NULL;
// pwm
static uint32_t pwm_freq = 10;
// 烹饪
static Cook *cook;

// 回调：tick，读ds18b20
static void cbReadCal(void *arg)
{
	DS18b20 *ds = (DS18b20 *)arg;
	counter++;
	if (counter >= COUNT)
	{
		// 读dsa18b20
		ds->begin_conversion();
		Input = ds->getTemp();
		// 计算PID
		myPID->Compute();
		//printf("main,t:%2.2f,out:%2.2f\n", Input, Output);
		//mgos_pwm_set(DRIVER, FREQ, Output);

		counter = 0;
	}
}

// 回调：Blynk云
static void cbPush(void *arg)
{
	struct mg_connection *c = get_connetion();
	if (c != NULL)
	{
		blynk_virtual_write(c, 0, Setpoint, 10); // V0 V1 V2
		blynk_virtual_write(c, 1, Input, 10);
		blynk_virtual_write(c, 2, Output, 10);

		c = NULL;
	}

	(void)arg;
}

static void cbBlynk(struct mg_connection *c, const char *cmd,
					int pin, int val, int id, void *user_data)
{
	//s_blynk_conn = c;
	double temp = 0;

	if (strcmp(cmd, "vr") == 0) // 读
	{
		switch (pin)
		{
		case 0: // v0
			temp = Setpoint;
			break;
		case 1:
			temp = Input;
			break;
		case 2:
			temp = Output;
			break;
		case v_temp:
			temp = Input;
			break;
		}
		blynk_virtual_write(c, pin, temp, id);
	}
	else if (strcmp(cmd, "vw") == 0) // 写
	{
		switch (pin)
		{
		case v_btn_egg: // 按钮： 鸡蛋
			printf("button v3,val:%d\n", val);
			if (val == 1)
			{
				blynk_virtual_write(c, v_led, 255, id); // v7
				LOG(LL_INFO, ("btn egg\n"));
				// 增加data
				mData data_egg = {63.0, 7200};
				cook->add_data(data_egg);
				cook->start();
			}
			else
			{
				blynk_virtual_write(c, v_led, 0, id);
				cook->stop();
			}

			break;

		case v_slider: // 滑条：负荷
			Output = (100 - val) / 100.0;
			mgos_pwm_set(DRIVER, FREQ, Output);
			mgos_pwm_set(FAN, pwm_freq, Output);
			break;

		case v_freq_levle: // 水平：载波频率
			pwm_freq = val * 1000;
			mgos_pwm_set(FAN, pwm_freq, Output);
			break;
		}
	}
	(void)user_data;
}

enum mgos_app_init_result mgos_app_init(void)
{
	//init
	Setpoint = 36;
	DS18b20 *ds18b20 = new DS18b20(DATA_DS18B20);
	ds18b20->init();
	// PID采样时间
	myPID = new PID(&Input, &Output, &Setpoint, consKp, consKi, consKd, DIRECT);
	myPID->SetSampleTime(1000);
	myPID->SetMode(AUTOMATIC);
	myPID->SetOutputLimits(0, 0.9f);
	// 定时读ds18b20，计算pid输出, 10ms
	mgos_set_timer(10, true, cbReadCal, ds18b20);
	// Blynk 云
	mgos_blynk_init();
	blynk_set_handler(cbBlynk, NULL);
	mgos_set_timer(5000, true, cbPush, NULL);
	// 烹饪
	cook = new Cook();

	return MGOS_APP_INIT_SUCCESS;
}
